import List "mo:base/List";
import Iter "mo:base/Iter";
import Principal "mo:base/Principal";
import Time "mo:base/Time";
import Array "mo:base/Array";

actor {

public type Message = {
   time : Time.Time;
   text : Text;
   author: ?Text;
};

public type Microblog = actor {
    follow: shared(Principal)-> async (); //添加关注对象
    unfollow: shared()-> async (); //清空关注
    follows: shared query () -> async [Principal]; //返回关注列表
    follows_name: shared  () -> async [Text]; //返回关注列表名称
    post: shared (Text) -> async ();  //发布微博
    posts: shared query (Time.Time) -> async [Message];  //展示指定时刻之后的微博
    otherposts: shared (Principal,Time.Time) -> async [Message];  //查询指定id，指定时间之后的微博
    timeline: shared () -> async [Message];  //查看时间线
    set_name:shared (Text)-> async ();  //设定名称 
    get_name:shared ()-> async ?Text;  //查看名称
    };


  stable var followed: List.List<Principal> = List.nil();

  public shared func follow(id : Principal) : async () {
    followed := List.push(id,followed);
  };
  public shared func unfollow() : async () {
    followed := List.nil();
  };
  public shared query func follows() : async [Principal]{
    List.toArray(followed)
  };

 stable var name:?Text = ?"comweb3"; //comweb3
 public shared func set_name(sname:Text) : async () {
    name := ?sname;
  };

  public shared func get_name():async ?Text{
    //     switch name {
    // case  ""    {null};
    // case (_)   {?name};};
  name;
    
};

  public shared func follows_name() : async [?Text]{
    var followed_name: List.List<?Text> = List.nil();
    for (user in Iter.fromList(followed)){
    let canister_user: Microblog = actor(Principal.toText(user));
    let username :?Text = await canister_user.get_name();
    // if (username == null) username := Principal.toText(user);
    followed_name := List.push(username,followed_name);
    };
    Array.reverse(List.toArray(followed_name))
  };
  

  stable var messages: List.List<Message> = List.nil();

  public shared (user) func post(text:Text):async () {
    // assert(Principal.toText(user.caller)=="6axso-2bbmh-43arq-uqvwy-scpuo-qijcs-zlamd-7ldxf-73er2-f4rby-uae");
    let new_message:Message = {
       time = Time.now();
       text = text;
       author= name;
    };
    messages := List.push(new_message,messages);
  };
  // public shared query func posts():async [Message]{
  //   List.toArray(messages)
  // };
  public shared query func posts(since:Time.Time):async [Message]{
    
    var after_messages: List.List<Message> = List.nil();

    for (mg in Iter.fromList(messages)){
    if (mg.time - since > 0) after_messages := List.push(mg,after_messages);
    };
    List.toArray(after_messages)
  };

  public shared func otherposts(id : Text,since:Time.Time):async [Message]{
    let canister_other : Microblog = actor(id);
    let msgs_other = await canister_other.posts(since:Time.Time);
    var after_messages: List.List<Message> = List.nil();

    for (mg in Iter.fromArray(msgs_other)){
    if (mg.time - since > 0) after_messages := List.push(mg,after_messages);
    };
    List.toArray(after_messages)
  };


  public shared func timeline(since:Time.Time):async [Message]{
    var all :List.List<Message> = List.nil();
    
    for (id in Iter.fromList(followed)){
        let canister : Microblog = actor(Principal.toText(id));
        let msgs = await canister.posts(since:Time.Time);
        for (msg in Iter.fromArray(msgs)){
          all := List.push(msg,all)
        }
    };
    List.toArray(all)
  };

};
